# 此文件是项目的中枢神经
import os
from flask import Flask

from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
from flask_cors import CORS

from redis import StrictRedis

from common.utils import converters
from app.settings import constants

from app.settings.config import config_dict
from app.tasks import create_celery

APP_CONFIG = os.getenv("APP_CONFIG", "dev")

redis_clent = None
celery = None
app = None
serializer = Marshmallow()
admin = None


def flask_app(config_tpye):
    """创建app"""
    global app
    app = Flask(__name__)
    # 加载配置信息
    app.config.from_object(config_dict[config_tpye])
    # 加载秘密key
    app.config.from_envvar(constants.EXTRA_ENV_COINFIG, silent=True)
    # 防止跨域
    CORS(app, supports_credentials=True)

    return app


def create_marshmallows(app):
    serializer.init_app(app)


def create_db(app):
    """创建数据库对象"""
    from app.models import db

    db.init_app(app)
    global redis_clent
    redis_clent = StrictRedis(
        host=app.config["REDIS_HOST"], port=app.config["REDIS_PORT"], decode_responses=True
    )

    # 注册模型类
    Migrate(app, db)
    from app.models.hello import Hello
    from app.models.car import CarInfo
    from app.models.user import User, Role, PermissionPath, PermissionPathSon
    from app.models.collection import DataCollection, ParkingCollection

    from app.models.ruel_cost import RuelCost
    from app.models.road_toll import RoadToll

    from app.models.parking_rate import ParkingRate


def register_extensions(app):
    """初始化组件"""
    # 添加路由转换器
    converters.register_converters(app)

    # 添加请求钩子
    from common.utils.middlewares import get_userinfo

    app.before_request(get_userinfo)


def create_blueprint(app):
    from app.routes import bp

    app.register_blueprint(bp)


# 创建app
def create_app(config_type=APP_CONFIG):
    """
    :param config_type: config_type：dev或线上配置
    :return:
    """
    # 生成app
    app = flask_app(config_type)
    # 数据库初始化
    create_db(app)
    # 生成admin后台
    from app.admin import create_model_admin

    create_model_admin(app)
    # 序列化器对象
    create_marshmallows(app)
    # 生成celery
    global celery
    celery = create_celery(app)
    # 注册蓝图
    create_blueprint(app)
    # 注册组件
    register_extensions(app)

    return app


# celery需要在此地生成app
app = create_app(APP_CONFIG)
